package com.neusoft.neuiotms.dcom.service.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import javax.persistence.EntityNotFoundException;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Workbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;

import com.neusoft.bizcore.auth.common.bean.UserBean;
import com.neusoft.bizcore.web.constant.ExceptionConstants;
import com.neusoft.bizcore.web.exception.UnitedException;
import com.neusoft.bizcore.web.support.Searchable;
import com.neusoft.neuiotms.common.dto.DictionaryDTO;
import com.neusoft.neuiotms.common.service.DictionaryService;
import com.neusoft.neuiotms.dcom.constants.DCOMConstants;
import com.neusoft.neuiotms.dcom.converter.InspectionTaskConverter;
import com.neusoft.neuiotms.dcom.dto.FunctionalGroupDTO;
import com.neusoft.neuiotms.dcom.dto.InspectionTaskDTO;
import com.neusoft.neuiotms.dcom.model.InspectionTask;
import com.neusoft.neuiotms.dcom.model.InspectionTaskProject;
import com.neusoft.neuiotms.dcom.model.InspectionTaskProjectItemValue;
import com.neusoft.neuiotms.dcom.model.enums.InspectionItemValueStatus;
import com.neusoft.neuiotms.dcom.model.enums.InspectionTaskStatus;
import com.neusoft.neuiotms.dcom.repository.InspectionTaskRepository;
import com.neusoft.neuiotms.dcom.service.FunctionalGroupService;
import com.neusoft.neuiotms.dcom.service.InspectionTaskService;

import cn.afterturn.easypoi.excel.ExcelExportUtil;
import cn.afterturn.easypoi.excel.entity.TemplateExportParams;
import cn.afterturn.easypoi.util.PoiMergeCellUtil;
import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class InspectionTaskServiceImpl implements InspectionTaskService {

    @Autowired
    private InspectionTaskRepository taskRepository;

    @Autowired
    private InspectionTaskConverter taskConverter;

    @Autowired
    private DictionaryService dictionaryService;

    @Autowired
    private FunctionalGroupService functionalGroupService;

    @Override
    public List<InspectionTaskDTO> index(final Searchable searchable) {
        final List<InspectionTask> model = this.taskRepository.index(searchable);
        return this.taskConverter.toListDTO(model);
    }

    @Override
    public Page<InspectionTaskDTO> page(final Searchable searchable, final Pageable pageable, final UserBean user) {
        final String statistics = searchable.getStrValue("statistics");
        Page<InspectionTaskDTO> dtos = new PageImpl<>(new ArrayList<InspectionTaskDTO>());
        if (!StringUtils.isEmpty(statistics)) {//如果是统计页面，按部门查询
            searchable.put("orgCodes", user.getOrgs());
            dtos = this.taskConverter.toPageDTO(this.taskRepository.page(searchable, pageable));
        } else {//如果是任务页面，按同一部门同一职能 查询
            final Searchable searchable1 = new Searchable();
            searchable1.put("username", user.getUsername());
            final List<Long> functionIds = this.functionalGroupService.index(searchable1).stream()
                    .map(FunctionalGroupDTO::getId).collect(Collectors.toList());

            if (!functionIds.isEmpty()) {
                searchable.put("functionIds", functionIds);
                dtos = this.taskConverter.toPageDTO(this.taskRepository.page(searchable, pageable));
            }
        }
        return dtos;

    }

    @Override
    public InspectionTaskDTO update(final Long id, final InspectionTaskDTO dto) {
        InspectionTask model;
        try {
            model = this.taskRepository.getOne(id);
        } catch (final EntityNotFoundException e) {
            InspectionTaskServiceImpl.log.error(e.getMessage(), e);
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }

        final Date now = new Date();
        final Double difference = this.getDifferenceFromDictionaryToNow(now);
        if ((now.getTime() - dto.getEndTaskTime().getTime()) > difference) {
            dto.setStatus(InspectionTaskStatus.overtimeUnfinished.name());
        }

        model = this.taskConverter.toModel(dto);
        this.taskRepository.save(model);
        return this.taskConverter.toDTO(model);
    }

    @Override
    public InspectionTaskDTO submit(final Long id, final InspectionTaskDTO dto, final UserBean user) {
        InspectionTask model;
        try {
            model = this.taskRepository.getOne(id);
        } catch (final EntityNotFoundException e) {
            InspectionTaskServiceImpl.log.error(e.getMessage(), e);
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }

        final Date now = new Date();
        final Double difference = this.getDifferenceFromDictionaryToNow(now);
        if ((now.getTime() - dto.getEndTaskTime().getTime()) > difference) {
            dto.setStatus(InspectionTaskStatus.overtimeFinished.name());
        } else {
            dto.setStatus(InspectionTaskStatus.finished.name());
        }

        dto.setFinishTaskTime(now);
        dto.setUsercode(user.getUsername());
        dto.setUsername(user.getName());
        model = this.taskConverter.toModel(dto);
        this.taskRepository.save(model);
        return this.taskConverter.toDTO(model);
    }

    private Double getDifferenceFromDictionaryToNow(final Date now) {
        final List<DictionaryDTO> dicts =
                this.dictionaryService.findByDictionaryType(DCOMConstants.INSPECTION_OVERTIME_TYPE);
        Double difference = 24 * 3600 * 1000d;
        if ((dicts != null) && !dicts.isEmpty()) {
            try {
                difference = Double.valueOf(dicts.get(0).getText()) * 3600 * 1000;
            } catch (final Exception e) {
                InspectionTaskServiceImpl.log.error("超时时间设置有误，使用默认时间（24h）");
            }
        }
        return difference;
    }

    @Override
    public InspectionTaskDTO detail(final Long id) {
        try {
            final InspectionTask model = this.taskRepository.getOne(id);
            return this.taskConverter.toDTO(model);
        } catch (final EntityNotFoundException e) {
            InspectionTaskServiceImpl.log.error(e.getMessage(), e);
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }
    }

    @Override
    public void delete(final Long id) {
        // TODO Auto-generated method stub

    }

    @Override
    public void claim(final Long id, final UserBean user) {
        try {
            final InspectionTask model = this.taskRepository.findById(id).get();
            model.setGetTaskTime(new Date());
            final Date now = new Date();
            final Double difference = this.getDifferenceFromDictionaryToNow(now);

            if ((now.getTime() - model.getEndTaskTime().getTime()) > difference) {
                model.setStatus(InspectionTaskStatus.overtimeUnfinished);
            } else {
                model.setStatus(InspectionTaskStatus.inspecting);
            }
            if (user != null) {
                model.setClaimCode(user.getUsername());
                model.setClaimName(user.getName());
            }
            this.taskRepository.save(model);
        } catch (final EntityNotFoundException e) {
            InspectionTaskServiceImpl.log.error(e.getMessage(), e);
            throw new UnitedException(ExceptionConstants.ENTITY_NOT_FOUND, new Object[] {id });
        }
    }

    @Override
    public Workbook download(final Searchable searchable) {
        final Map<String, Object> value = this.getData(searchable);
        final TemplateExportParams params = new TemplateExportParams(
                "excel/inspectionTask.xlsx");
        params.setColForEach(true);
        final Workbook workbook = ExcelExportUtil.exportExcel(params, value);
        PoiMergeCellUtil.mergeCells(workbook.getSheetAt(0), 1, 0, 1);
        return workbook;
    }

    public Map<String, Object> getData(final Searchable searchable) {
        //        searchable.put("inspecitonRuleId", "3");
        final List<InspectionTask> list = this.taskRepository.index(searchable);

        final Map<String, Object> value = new HashMap<>();
        final List<Map<String, Object>> colList = new ArrayList<>();
        final List<Map<String, Object>> valList = new ArrayList<>();

        for (final InspectionTask t : list) {
            //表头
            final Map<String, Object> col = new HashMap<>();
            col.put("time", t.getStartTaskTime());
            col.put("inspectionName", "巡检项名称");

            col.put("inspectionValue", "巡检项值");
            col.put("inspectionUnit", "巡检项单位");
            col.put("status", "巡检项状态");
            col.put("itemName", "t.itemName" + t.getId());

            col.put("itemValue", "t.itemValue" + t.getId());
            col.put("itemUnit", "t.itemUnit" + t.getId());
            col.put("itemStatus", "t.itemStatus" + t.getId());
            colList.add(col);
            //拼数据
            for (final InspectionTaskProject p : t.getInspectionTaskProject()) {
                for (final InspectionTaskProjectItemValue i : p.getItemValue()) {
                    boolean flag = false;
                    Map<String, Object> map = new HashMap<>();
                    for (final Map<String, Object> m : valList) {
                        if ((m.get("id") != null)
                                && (Long.valueOf(m.get("id").toString()).longValue() == i.getRuleProjectItem().getId()
                                        .longValue())) {
                            map = m;
                            flag = true;
                            break;
                        }
                    }
                    map.put("itemName" + t.getId(), i.getRuleProjectItem().getName());
                    String status = "未巡检";
                    if (i.getStatus() == InspectionItemValueStatus.uninspected) {
                        status = "未巡检";
                    } else if (i.getStatus() == InspectionItemValueStatus.normal) {
                        status = "正常";
                    } else if (i.getStatus() == InspectionItemValueStatus.earlyWarning) {
                        status = "预警";
                    } else if (i.getStatus() == InspectionItemValueStatus.alarm) {
                        status = "告警";
                    }
                    map.put("itemStatus" + t.getId(), status);
                    map.put("itemValue" + t.getId(), i.getValue());
                    map.put("itemUnit" + t.getId(), i.getRuleProjectItem().getUnit());

                    if (!flag) {
                        map.put("locationName", p.getLocationName());
                        map.put("concreteName", p.getConcreteName());
                        map.put("id", i.getRuleProjectItem().getId());
                        valList.add(map);
                    }
                }
            }
        }
        value.put("colList", colList);
        value.put("valList", valList);
        return value;
    }

}
